/*
  Copyright (c) 2002, 2003 Russell Morris
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 
  are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 
      
    * Redistributions in binary form must reproduce the above copyright notice, 
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 
      
    * The names of the contributors may not be used to endorse or promote 
      products derived from this software without specific prior written permission. 
      
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
    IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
    THE POSSIBILITY OF SUCH DAMAGE.
*/

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WRM.Windows.Forms
{
  /// <summary>
  ///    <para>
  ///    A header for <see cref="PropertyPane"/>s in the 
  ///    <see cref="PropertyTree"/>.
  ///    </para>
  /// </summary>
  public class PaneHeader : System.Windows.Forms.Control
  {
    /// <summary>
    ///    Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components;

    /// <summary>
    /// The left color of the non-Themed gradient
    /// </summary>
    private Color mLeftColor;

    /// <summary>
    /// The right color of the non-Themed gradient
    /// </summary>
    private Color mRightColor;

    /// <summary>
    /// The brush that draws the non-Themed gradient
    /// </summary>
    private LinearGradientBrush mGradBrush;

    /// <summary>
    /// Our client rectangle
    /// </summary>
    private Rectangle mOurRect;

    /// <summary>
    /// The rectangle our text will be drawn into
    /// </summary>
    private RectangleF mTextRect;

    /// <summary>
    ///  Creates a new instance of the PaneHeader class
    /// </summary>
    public PaneHeader()
    {
      // This call is required by the WinForms Form Designer.
      InitializeComponent();

      mTextRect = new RectangleF(0f,0f,1f,1f);
      mLeftColor = SystemColors.ActiveCaption;
      mRightColor = SystemColors.Control;
      ForeColor = SystemColors.ActiveCaptionText;
      CreateBrush();
    }

    /// <summary>
    ///    Clean up any resources being used.
    /// </summary>
    /// <param name="isDisposing">
    /// <c>true</c> to release both managed and unmanaged resources; 
    /// <c>false</c> to release only unmanaged resources.
    /// </param>
    protected override void Dispose(bool isDisposing)
    {
      if(mGradBrush != null)
        mGradBrush.Dispose();  

      base.Dispose(isDisposing);
    }

    /// <summary>
    ///    Required method for Designer support - do not modify 
    ///    the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.components = new System.ComponentModel.Container ();
      //@this.TrayLargeIcon = false;
      //@this.TrayAutoArrange = true;
      //@this.TrayHeight = 0;
      this.Size = new System.Drawing.Size (276, 20);
      this.Font = new System.Drawing.Font ("Tahoma", 8);
    }

    /// <summary>
    /// Override to handle background painting.
    /// </summary>
    /// <param name="e">Event information</param>
    /// <remarks>
    /// No background painting occurs, and the base class's version of
    /// <see cref="Control.OnPaintBackground">OnPaintBackground</see> 
    /// is not called.
    /// </remarks>
    protected override void OnPaintBackground(PaintEventArgs e)
    {
    }
      
    /// <summary>
    /// Override to handle painting.
    /// </summary>
    /// <param name="e">Paint event information</param>
    /// <remarks>
    /// <c>PaneHeader</c>'s background is drawn using a horizontal 
    /// gradient from <see cref="PaneHeader.LeftColor"/> to 
    /// <see cref="PaneHeader.RightColor"/>.
    /// </remarks>
    protected override void OnPaint(PaintEventArgs e)
    {
      //Paint the gradient
      //
      e.Graphics.FillRectangle(mGradBrush,0,0,Width,Height);

      //And now the text
      //
      e.Graphics.DrawString(
        Text,
        Font,
        new SolidBrush(ForeColor),
        mTextRect);
    }

    /// <summary>
    ///   Override to handle the Resize event.
    /// </summary>
    /// <param name="e">Resize event information</param>
    /// <remarks>
    /// This function is overridden so that the entire background will be
    /// invalidated, and the gradient brush re-created, every time the 
    /// canvas changes size.
    /// </remarks>
    protected override void OnResize(EventArgs e)
    {
      base.OnResize(e);
      Invalidate(ClientRectangle,false);
      CreateBrush();
    }

    /// <summary>
    /// Creates the <see cref="Brush"/> object used to paint the 
    /// background gradient.
    /// </summary>
    protected void CreateBrush()
    {
      mTextRect = new RectangleF(0f,0f,(float)Width,(float)Height);

      mOurRect = new Rectangle(0,0,Width,Height);

      if(mGradBrush != null)
        mGradBrush.Dispose();

      mGradBrush = new LinearGradientBrush(mOurRect,
        mLeftColor,
        mRightColor,
        LinearGradientMode.Horizontal);
    }
      
    /// <summary>
    /// Gets or sets the color on the left-hand side of the background gradient.
    /// </summary>
    /// <value>
    /// This value represents the color on the left side of the background gradient.
    /// </value>
    /// <remarks>
    /// Setting this value to a new color will cause the gradient brush to be recreated
    /// via <see cref="PaneHeader.CreateBrush"/> and the entire client rectangle will be 
    /// invalidated.
    /// </remarks>
    [Description("The color on the left-hand side of the gradient")]
    [Category("Appearance")]
    public Color LeftColor 
    {
      get 
      {
        return mLeftColor;
      }
      set 
      {
        mLeftColor = value;
        CreateBrush();
        Invalidate();
      }
    }

    /// <summary>
    /// Gets or sets the color on the right-hand side of the background gradient.
    /// </summary>
    /// <value>
    /// This value represents the color on the right side of the background gradient.
    /// </value>
    /// <remarks>
    /// Setting this value to a new color will cause the gradient brush to be recreated
    /// via <see cref="PaneHeader.CreateBrush"/> and the entire client rectangle will be 
    /// invalidated.
    /// </remarks>
    [Description("The color on the right-hand side of the gradient")]
    [Category("Appearance")]
    public Color RightColor
    {
      get 
      {
        return mRightColor;
      }
      set 
      {
        mRightColor = value;
        CreateBrush();
        Invalidate();
      }
    }

    /// <summary>
    /// Override to handle the TextChanged event.
    /// </summary>
    /// <param name="e">Event information</param>
    /// <remarks>
    /// When the <see cref="Control.Text">Text</see> property changes, the
    /// entire client rectangle needs to be invalidated and redrawn.
    /// </remarks>
    protected override void OnTextChanged(System.EventArgs e)
    {
      Invalidate(ClientRectangle,false);
      Update();
    }
  }
}
